package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.service.RabbitService;
import com.atguigu.gmall.service.config.MqConst;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@SuppressWarnings("all")
public class OrderInfoServiceImpl implements OrderInfoService {

    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CartInfoMapper cartInfoMapper;

    //判断是否有货
    @Override
    public boolean hasStock(Long skuId, Integer skuNum) {

        return "1".equals(HttpClientUtil.doGet(
                "http://localhost:9001/hasStock?skuId=" + skuId + "&num=" + skuNum));
    }

    @Override
    @Transactional
    public Long saveOrder(OrderInfo orderInfo) {
        //1、订单表 订单主表
        //   订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //   订单交易编号
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis();
        orderInfo.setOutTradeNo(outTradeNo);
        //   订单描述（支付原因
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        for (OrderDetail orderDetail : orderDetailList) {
            sb.append(orderDetail.getSkuName());
        }
        if (sb.length() > 100) {
            orderInfo.setTradeBody(sb.toString().substring(0, 100));
        } else {
            orderInfo.setTradeBody(sb.toString());
        }
        //   创建时间  -->
        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());
        //   失效时间设置 2小时
        calendar.add(Calendar.HOUR,2);
        orderInfo.setExpireTime(calendar.getTime());
        //   进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //   总金额 重新计算
        for (OrderDetail orderDetail : orderDetailList) {
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
        }
        orderInfo.sumTotalAmount();
        //   保存订单 --> 返回ID值
        orderInfoMapper.insert(orderInfo);

        List<String> skuIds = new ArrayList<>(orderDetailList.size());
        //2、订单详情表 商品清单
        orderDetailList.forEach(orderDetail -> {
            //获取订单主表的ID
            orderDetail.setOrderId(orderInfo.getId());
            skuIds.add(String.valueOf(orderDetail.getSkuId()));
            //保存订单详情
            orderDetailMapper.insert(orderDetail);
        });
        //3、删除购物车中已购买商品
        QueryWrapper queryWrapper = new QueryWrapper<CartInfo>();
        queryWrapper.eq("user_id",orderInfo.getUserId());
        queryWrapper.in("sku_id",skuIds);
        cartInfoMapper.delete(queryWrapper);
        //   可变参数，批量删除缓存，性能高
        String cacheKey = RedisConst.USER_KEY_PREFIX +
                orderInfo.getUserId() + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheKey,skuIds.toArray());

        //4、TODO MQ延迟消息 完成 订单过期后的取消操作
        /*rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL,orderInfo.getId(),15);*/

        return orderInfo.getId();
    }

    @Override
    public void cancelOrder(Long orderId) {
        //1、查询订单 只有未支付状态 才会取消订单
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (null != orderInfo &&
                orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
            //发消息MQ 通知支付微服务
            //关闭支付宝交易
            //取消订单
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            orderInfoMapper.updateById(orderInfo);
            //TODO 取消订单后续工作
            System.out.println("取消订单成功");
        }
    }

    @Override
    //只查询订单信息
    public OrderInfo getOrderInfo(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }
    //查询订单信息和订单详情表
    public OrderInfo getOrderInfoAndDetail(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(
                new QueryWrapper<OrderDetail>().eq("order_id", orderId));
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }

    @Override
    public void updateOrder(Long orderId) {
        //考虑幂等性问题
        OrderInfo orderInfo = getOrderInfo(orderId);
        if (null != orderInfo &&
                orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
            //改为已支付
            orderInfo.setOrderStatus(OrderStatus.PAID.name());
            orderInfo.setProcessStatus(ProcessStatus.PAID.name());
            //更新订单
            orderInfoMapper.updateById(orderInfo);
        }

        //发送消息MQ 库存微服务修改
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                MqConst.ROUTING_WARE_STOCK,initWareOrder(orderId));

    }

    //更新订单状态
    @Override
    public void updateOrder(String orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();//TODO 存疑，不应该先查出OrderInfo再改吗
        orderInfo.setId(Long.parseLong(orderId));
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.selectById(orderInfo);
    }

    //开始拆单
    @Override
    public List<OrderInfo> orderSpilt(Long orderId, String wareSkuMap) {
        List<OrderInfo> orderInfoList = new ArrayList<>();

        // wareSkuMap : [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
        // 原订单 父订单
        OrderInfo OriginOrderInfo = getOrderInfoAndDetail(orderId);
        // 新订单 子订单
        List<Map> listMap = JSONObject.parseArray(wareSkuMap, Map.class);
        for (Map map : listMap) {
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(OriginOrderInfo,subOrderInfo);
            //设置仓库Id
            subOrderInfo.setWareId(String.valueOf(map.get("wareId")));
            //子订单ID自增长,并且有父订单编号
            subOrderInfo.setId(null);
            subOrderInfo.setParentOrderId(OriginOrderInfo.getId());

            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            //订单详情表
            List<OrderDetail> orderDetailList = OriginOrderInfo.getOrderDetailList();
            List<String> skuIds = (List<String>) map.get("skuIds");
            for (OrderDetail orderDetail : orderDetailList) {
                for (String skuId : skuIds) {
                    if (orderDetail.getSkuId().equals(Long.parseLong(skuId))){
                        subOrderDetailList.add(orderDetail);
                        break;
                    }
                }
            }
            //子订单设置拆开后的子订单详情集合
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //子订单 总金额
            subOrderInfo.sumTotalAmount();

            //添加一个子订单
            orderInfoList.add(subOrderInfo);

            //修改DB
            orderInfoMapper.insert(subOrderInfo);
            //修改订单详情表
            subOrderDetailList.forEach(subOrderDetail -> {
                //外键
                subOrderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(subOrderDetail);
            });
        }
        //修改原订单状态为已拆单
        OriginOrderInfo.setOrderStatus(OrderStatus.SPLIT.name());
        OriginOrderInfo.setProcessStatus(ProcessStatus.SPLIT.name());
        orderInfoMapper.updateById(OriginOrderInfo);
        return orderInfoList;
    }

    //构建库存微服务需要的json串数据 HTTP请求
    public String initWareOrder(Long orderId){
        //幂等性问题
        OrderInfo orderInfo = getOrderInfoAndDetail(orderId);
        Map map = new HashMap();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("orderComment",orderInfo.getOrderComment());
        map.put("orderBody",orderInfo.getTradeBody());
        map.put("deliveryAddress",orderInfo.getDeliveryAddress());
        //需要传1或2 而非Online
        map.put("paymentWay","ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        //组装嵌套的订单详情表json串
        List<OrderDetail> detailList = orderInfo.getOrderDetailList();
        List<Map> details = detailList.stream().map(orderDetail -> {
            Map detailMap = new HashMap();
            detailMap.put("skuId",orderDetail.getSkuId());
            detailMap.put("skuName",orderDetail.getSkuName());
            detailMap.put("skuNum",orderDetail.getSkuNum());
            return detailMap;
        }).collect(Collectors.toList());
        map.put("details",details);

        return JSONObject.toJSONString(map);
    }

    //重载上面的方法
    public Map initWareOrder(OrderInfo orderInfo){
        Map map = new HashMap();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("orderComment",orderInfo.getOrderComment());
        map.put("orderBody",orderInfo.getTradeBody());
        map.put("deliveryAddress",orderInfo.getDeliveryAddress());
        //需要传1或2 而非Online
        map.put("paymentWay","ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        //仓库Id
        map.put("wareId",orderInfo.getWareId());
        //组装嵌套的订单详情表json串
        List<OrderDetail> detailList = orderInfo.getOrderDetailList();
        List<Map> details = detailList.stream().map(orderDetail -> {
            Map detailMap = new HashMap();
            detailMap.put("skuId",orderDetail.getSkuId());
            detailMap.put("skuName",orderDetail.getSkuName());
            detailMap.put("skuNum",orderDetail.getSkuNum());
            return detailMap;
        }).collect(Collectors.toList());
        map.put("details",details);
        return map;
    }

    @Autowired
    private RabbitService rabbitService;
}
